# LocalStack Resource Provider Scaffolding v2
from __future__ import annotations

import logging
from pathlib import Path
from typing import Optional, TypedDict

import localstack.services.cloudformation.provider_utils as util
from localstack.constants import AWS_REGION_US_EAST_1, DEFAULT_AWS_ACCOUNT_ID
from localstack.services.cloudformation.resource_provider import (
    OperationStatus,
    ProgressEvent,
    ResourceProvider,
    ResourceRequest,
)
from localstack.utils.aws import arns

LOG = logging.getLogger(__name__)

# simple mock state
default_repos_per_stack = {}


class ECRRepositoryProperties(TypedDict):
    Arn: Optional[str]
    EncryptionConfiguration: Optional[EncryptionConfiguration]
    ImageScanningConfiguration: Optional[ImageScanningConfiguration]
    ImageTagMutability: Optional[str]
    LifecyclePolicy: Optional[LifecyclePolicy]
    RepositoryName: Optional[str]
    RepositoryPolicyText: Optional[dict | str]
    RepositoryUri: Optional[str]
    Tags: Optional[list[Tag]]


class LifecyclePolicy(TypedDict):
    LifecyclePolicyText: Optional[str]
    RegistryId: Optional[str]


class Tag(TypedDict):
    Key: Optional[str]
    Value: Optional[str]


class ImageScanningConfiguration(TypedDict):
    ScanOnPush: Optional[bool]


class EncryptionConfiguration(TypedDict):
    EncryptionType: Optional[str]
    KmsKey: Optional[str]


REPEATED_INVOCATION = "repeated_invocation"


class ECRRepositoryProvider(ResourceProvider[ECRRepositoryProperties]):
    TYPE = "AWS::ECR::Repository"  # Autogenerated. Don't change
    SCHEMA = util.get_schema_path(Path(__file__))  # Autogenerated. Don't change

    def create(
        self,
        request: ResourceRequest[ECRRepositoryProperties],
    ) -> ProgressEvent[ECRRepositoryProperties]:
        """
        Create a new resource.

        Primary identifier fields:
          - /properties/RepositoryName

        Create-only properties:
          - /properties/RepositoryName
          - /properties/EncryptionConfiguration
          - /properties/EncryptionConfiguration/EncryptionType
          - /properties/EncryptionConfiguration/KmsKey

        Read-only properties:
          - /properties/Arn
          - /properties/RepositoryUri

        IAM permissions required:
          - ecr:CreateRepository
          - ecr:PutLifecyclePolicy
          - ecr:SetRepositoryPolicy
          - ecr:TagResource
          - kms:DescribeKey
          - kms:CreateGrant
          - kms:RetireGrant

        """
        model = request.desired_state

        default_repos_per_stack[request.stack_name] = model["RepositoryName"]
        LOG.warning(
            "Creating a Mock ECR Repository for CloudFormation. This is only intended to be used for allowing a successful CDK bootstrap and does not provision any underlying ECR repository."
        )
        model.update(
            {
                "Arn": arns.ecr_repository_arn(
                    model["RepositoryName"], DEFAULT_AWS_ACCOUNT_ID, AWS_REGION_US_EAST_1
                ),
                "RepositoryUri": "http://localhost:4566",
                "ImageTagMutability": "MUTABLE",
                "ImageScanningConfiguration": {"scanOnPush": True},
            }
        )
        return ProgressEvent(
            status=OperationStatus.SUCCESS,
            resource_model=model,
            custom_context=request.custom_context,
        )

    def read(
        self,
        request: ResourceRequest[ECRRepositoryProperties],
    ) -> ProgressEvent[ECRRepositoryProperties]:
        """
        Fetch resource information

        IAM permissions required:
          - ecr:DescribeRepositories
          - ecr:GetLifecyclePolicy
          - ecr:GetRepositoryPolicy
          - ecr:ListTagsForResource
        """
        raise NotImplementedError

    def delete(
        self,
        request: ResourceRequest[ECRRepositoryProperties],
    ) -> ProgressEvent[ECRRepositoryProperties]:
        """
        Delete a resource

        IAM permissions required:
          - ecr:DeleteRepository
          - kms:RetireGrant
        """
        if default_repos_per_stack.get(request.stack_name):
            del default_repos_per_stack[request.stack_name]

        return ProgressEvent(
            status=OperationStatus.SUCCESS,
            resource_model=request.desired_state,
            custom_context=request.custom_context,
        )

    def update(
        self,
        request: ResourceRequest[ECRRepositoryProperties],
    ) -> ProgressEvent[ECRRepositoryProperties]:
        """
        Update a resource

        IAM permissions required:
          - ecr:PutLifecyclePolicy
          - ecr:SetRepositoryPolicy
          - ecr:TagResource
          - ecr:UntagResource
          - ecr:DeleteLifecyclePolicy
          - ecr:DeleteRepositoryPolicy
          - ecr:PutImageScanningConfiguration
          - ecr:PutImageTagMutability
          - kms:DescribeKey
          - kms:CreateGrant
          - kms:RetireGrant
        """
        raise NotImplementedError
